package com.java202411.contoller.authorization;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.java202411.contoller.commons.NotAuthorizationException;
import com.java202411.entity.UserEntity;
import com.java202411.service.commons.NotFoundException;
import com.java202411.service.user.UserService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;

@Aspect
@Component
@RequiredArgsConstructor
public class AuthorizationAdvice {
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationAdvice.class);

    private final UserService userService;

    @Before("@annotation(com.java202411.contoller.authorization.RequireAuthorization)")
    public void checkAccessToken(JoinPoint joinPoint) {
        String accessToken = AuthorizationOfficer.getAccessToken();

        if (accessToken == null) {
            throw new NotAuthorizationException("Access token is required");
        }

        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("this is jwt secret")).build();
        DecodedJWT jwt;
        try {
            jwt = jwtVerifier.verify(accessToken);
        } catch (Exception exception) {
            throw new NotAuthorizationException("Access token is invalid");
        }

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        RequireAuthorization annotation = method.getAnnotation(RequireAuthorization.class);
        String requireRole = annotation.needRole();

        if (StringUtils.isBlank(requireRole)) {
            return;
        }

        String email = jwt.getClaim("email").asString();
        UserEntity user = userService.findByEmail(email)
                .orElseThrow(() -> new NotFoundException("用户不存在: " + email));

        LOGGER.info("current use is {}, api require role {}", email, requireRole);

        List<String> roles = user.getRoles();
        if (!roles.contains(requireRole)) {
            throw new NotAuthorizationException("role is not correct");
        }
    }
}